package utils

import (
	"crypto/hmac"
	"crypto/sha512"
	"encoding/hex"
	"fmt"
	"io"
	"log"
	"os"
	"ota-backend/config"
	"path/filepath"
)

// SignType 签名类型
type SignType string

const (
	SignTypeECC        SignType = "ECC"
	SignTypeRSA        SignType = "RSA"
	SignTypeHMACSHA512 SignType = "HMAC_SHA512"
)

// SignFile 对文件进行签名
func SignFile(filePath string, signType SignType, key string) (string, error) {
	// 获取存储根路径
	storagePath := config.GetStoragePath()
	// 构建完整路径
	fullPath := filepath.Join(storagePath, filePath)

	log.Printf("开始签名文件: path=%s, storagePath=%s, fullPath=%s, type=%s, key=%s", filePath, storagePath, fullPath, signType, key)

	// 检查文件是否存在
	if _, err := os.Stat(fullPath); os.IsNotExist(err) {
		log.Printf("文件不存在: %s", fullPath)
		return "", fmt.Errorf("文件不存在: %s", fullPath)
	}

	switch signType {
	case SignTypeHMACSHA512:
		return signFileHMACSHA512(fullPath, key)
	case SignTypeECC:
		return "", fmt.Errorf("ECC签名暂未实现")
	case SignTypeRSA:
		return "", fmt.Errorf("RSA签名暂未实现")
	default:
		return "", fmt.Errorf("不支持的签名类型: %s", signType)
	}
}

// signFileHMACSHA512 使用HMAC-SHA512对文件进行签名
func signFileHMACSHA512(filePath string, key string) (string, error) {
	// 打开文件
	file, err := os.Open(filePath)
	if err != nil {
		log.Printf("打开文件失败: path=%s, error=%v", filePath, err)
		return "", fmt.Errorf("打开文件失败: %v", err)
	}
	defer file.Close()

	// 创建HMAC-SHA512哈希对象
	h := hmac.New(sha512.New, []byte(key))

	// 读取文件内容并计算哈希
	if _, err := io.Copy(h, file); err != nil {
		log.Printf("计算哈希失败: path=%s, error=%v", filePath, err)
		return "", fmt.Errorf("计算哈希失败: %v", err)
	}

	// 获取哈希值并转换为十六进制字符串
	signature := hex.EncodeToString(h.Sum(nil))
	log.Printf("签名成功: path=%s, signature=%s", filePath, signature)
	return signature, nil
}

// VerifyFile 验证文件签名
func VerifyFile(filePath string, signType SignType, key string, signature string) (bool, error) {
	// 获取存储根路径
	storagePath := config.GetStoragePath()
	// 构建完整路径
	fullPath := filepath.Join(storagePath, filePath)

	switch signType {
	case SignTypeHMACSHA512:
		return verifyFileHMACSHA512(fullPath, key, signature)
	case SignTypeECC:
		return false, fmt.Errorf("ECC验证暂未实现")
	case SignTypeRSA:
		return false, fmt.Errorf("RSA验证暂未实现")
	default:
		return false, fmt.Errorf("不支持的签名类型: %s", signType)
	}
}

// verifyFileHMACSHA512 验证HMAC-SHA512签名
func verifyFileHMACSHA512(filePath string, key string, signature string) (bool, error) {
	// 计算文件的签名
	actualSignature, err := signFileHMACSHA512(filePath, key)
	if err != nil {
		return false, err
	}

	// 比较签名
	return actualSignature == signature, nil
}
